/**
  ******************************************************************************
  * @名字    msp430g2_gpio.c
  * @作者    lucien
  * @版本    V3.5.0
  * @日期    2019-08-18
  * @说明    这是一个MSP430G2的.
  ******************************************************************************
  * @声明
  *
  * 基于MSP430G2系列的硬件，提供底层操作函数，
  *
  ******************************************************************************
  */


#include "../inc/msp430g2_gpio.h"

//
// 名字
// 输入
// 返回
// 说明
//
void Gpio_DeInit(void)
{
    IFG1 &= ~OFIFG; // 清除晶振错误标志位

    P1DIR = 0xFF;   // 所有的P1端口都设置为输出
    P1OUT = 0;      // P1端口值都清零

    P2DIR = 0xFF;   // 所有的P2端口都设置为输出
    P2OUT = 0;      // P2端口值都清零

    P3DIR = 0xFF;   // 所有的P3端口都设置为输出
    P3OUT = 0;      // P3端口值都清零
}


#if 1
void Gpio_Init(GpioConfig_Def *GpioCfg)
{
    if(GpioCfg->GpioPort == GpioPort1)
    {
        switch(GpioCfg->GpioMode)
        {
            case GpioMode_OUT :
            {
                P1REN &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 禁止上下拉
                P1SEL &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 设置为普通IO口
                P1SEL2 &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));    // 设置为普通IO口
                P1DIR |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 设置为输出
            }break;

            case GpioMode_IPD :
            {
                P1SEL &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));
                P1SEL2 &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));    // 设置为普通IO口
                P1DIR &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 设置为输入
                P1REN |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 启用上下拉
                P1OUT &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 设置为下拉
            }break;

            case GpioMode_IPU :
            {
                P1SEL &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));
                P1SEL2 &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));    // 设置为普通IO口
                P1DIR &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 设置为输入
                P1REN |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 启用上下拉
                P1OUT |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 设置为上拉
            }break;

            case GpioMode_EXF :
            {
                P1REN &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 禁止上下拉
                P1SEL |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 设置为主外设模块功能
                P1SEL2 &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));    // PxSEL = 0b01
                P1DIR |= ((uint8_t)(0X01 << GpioCfg->GpioPin));
            }break;

            case GpioMode_ENC :
            {
                P1REN &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 禁止上下拉
                P1SEL &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 保留功能
                P1SEL2 |= ((uint8_t)(0X01 << GpioCfg->GpioPin));     // PxSEL = 0b10
                P1DIR |= ((uint8_t)(0X01 << GpioCfg->GpioPin));
            }break;

            case GpioMode_EXS :
            {
                P1REN &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 禁止上下拉
                P1SEL |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 设置为主外设模块功能
                P1SEL2 |= ((uint8_t)(0X01 << GpioCfg->GpioPin));     // PxSEL = 0b11
                P1DIR |= ((uint8_t)(0X01 << GpioCfg->GpioPin));
            }break;

            default: break;
        }
    }
    else if(GpioCfg->GpioPort == GpioPort2)
    {
        switch(GpioCfg->GpioMode)
        {
            case GpioMode_OUT :
            {
                P2REN &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 禁止上下拉
                P2SEL &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 设置为普通IO口
                P2SEL2 &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));    // 设置为普通IO口
                P2DIR |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 设置为输出
            }break;

            case GpioMode_IPD :
            {
                P2SEL &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));
                P2SEL2 &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));    // 设置为普通IO口
                P2DIR &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 设置为输入
                P2REN |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 启用上下拉
                P2OUT &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 设置为下拉
            }break;

            case GpioMode_IPU :
            {
                P2SEL &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));
                P2SEL2 &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));    // 设置为普通IO口
                P2DIR &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 设置为输入
                P2REN |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 启用上下拉
                P2OUT |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 设置为上拉
            }break;

            case GpioMode_EXF :
            {
                P2REN &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 禁止上下拉
                P2SEL |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 设置为主外设模块功能
                P2SEL2 &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));    // PxSEL = 0b01
                P2DIR |= ((uint8_t)(0X01 << GpioCfg->GpioPin));
            }break;

            case GpioMode_ENC :
            {
                P2REN &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 禁止上下拉
                P2SEL &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 保留功能
                P2SEL2 |= ((uint8_t)(0X01 << GpioCfg->GpioPin));     // PxSEL = 0b10
                P2DIR |= ((uint8_t)(0X01 << GpioCfg->GpioPin));
            }break;

            case GpioMode_EXS :
            {
                P2REN &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 禁止上下拉
                P2SEL |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 设置为主外设模块功能
                P2SEL2 |= ((uint8_t)(0X01 << GpioCfg->GpioPin));     // PxSEL = 0b11
                P2DIR |= ((uint8_t)(0X01 << GpioCfg->GpioPin));
            }break;

            default: break;
        }
    }
    else if(GpioCfg->GpioPort == GpioPort3)
    {
        switch(GpioCfg->GpioMode)
        {
            case GpioMode_OUT :
            {
                P3REN &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 禁止上下拉
                P3SEL &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 设置为普通IO口
                P3SEL2 &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));    // 设置为普通IO口
                P3DIR |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 设置为输出
            }break;

            case GpioMode_IPD :
            {
                P3SEL &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));
                P3SEL2 &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));    // 设置为普通IO口
                P3DIR &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 设置为输入
                P3REN |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 启用上下拉
                P3OUT &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 设置为下拉
            }break;

            case GpioMode_IPU :
            {
                P3SEL &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));
                P3SEL2 &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));    // 设置为普通IO口
                P3DIR &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 设置为输入
                P3REN |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 启用上下拉
                P3OUT |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 设置为上拉
            }break;

            case GpioMode_EXF :
            {
                P3REN &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 禁止上下拉
                P3SEL |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 设置为主外设模块功能
                P3SEL2 &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));    // PxSEL = 0b01
                P3DIR |= ((uint8_t)(0X01 << GpioCfg->GpioPin));
            }break;

            case GpioMode_ENC :
            {
                P3REN &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 禁止上下拉
                P3SEL &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 保留功能
                P3SEL2 |= ((uint8_t)(0X01 << GpioCfg->GpioPin));     // PxSEL = 0b10
                P3DIR |= ((uint8_t)(0X01 << GpioCfg->GpioPin));
            }break;

            case GpioMode_EXS :
            {
                P3REN &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 禁止上下拉
                P3SEL |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 设置为主外设模块功能
                P3SEL2 |= ((uint8_t)(0X01 << GpioCfg->GpioPin));     // PxSEL = 0b11
                P3DIR |= ((uint8_t)(0X01 << GpioCfg->GpioPin));
            }break;

            default: break;
        }
    }
    else
    {
        return;
    }

}


#else

void Gpio_Init(GpioConfig_Def *GpioCfg)
{
    SFR_8BIT(*PxSEL);
    SFR_8BIT(*PxSEL2);
    SFR_8BIT(*PxDIR);
    SFR_8BIT(*PxREN);
    SFR_8BIT(*PxOUT);

    if(GpioCfg->GpioPort == GpioPort1)
    {
        PxSEL = &P1SEL;
        PxSEL2 = &P1SEL2;
        PxDIR = &P1DIR;
        PxREN = &P1REN;
        PxOUT = &P1OUT;
    }
    else if(GpioCfg->GpioPort == GpioPort2)
    {
        PxSEL = &P2SEL;
        PxSEL2 = &P2SEL2;
        PxDIR = &P2DIR;
        PxREN = &P2REN;
        PxOUT = &P2OUT;
    }
    else if(GpioCfg->GpioPort == GpioPort3)
    {
        PxSEL = &P3SEL;
        PxSEL2 = &P3SEL2;
        PxDIR = &P3DIR;
        PxREN = &P3REN;
        PxOUT = &P3OUT;
    }
    else
    {
        return;
    }

    switch(GpioCfg->GpioMode)
    {
        case GpioMode_OUT :
        {
            *PxREN &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 禁止上下拉
            *PxSEL &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 设置为普通IO口
            *PxSEL2 &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));    // 设置为普通IO口
            *PxDIR |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 设置为输出
        }break;

                case GpioMode_IPD :
                {
                    *PxSEL &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));
                    *PxSEL2 &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));    // 设置为普通IO口
                    *PxDIR &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 设置为输入
                    *PxREN |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 启用上下拉
                    *PxOUT &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 设置为下拉
                }break;

                case GpioMode_IPU :
                {
                    *PxSEL &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));
                    *PxSEL2 &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));    // 设置为普通IO口
                    *PxDIR &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 设置为输入
                    *PxREN |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 启用上下拉
                    *PxOUT |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 设置为上拉
                }break;

                case GpioMode_EXF :
                {
                    *PxREN &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 禁止上下拉
                    *PxSEL |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 设置为主外设模块功能
                    *PxSEL2 &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));    // PxSEL = 0b01
                    *PxDIR |= ((uint8_t)(0X01 << GpioCfg->GpioPin));
                }break;

                case GpioMode_ENC :
                {
                    *PxREN &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 禁止上下拉
                    *PxSEL &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 保留功能
                    *PxSEL2 |= ((uint8_t)(0X01 << GpioCfg->GpioPin));     // PxSEL = 0b10
                    *PxDIR |= ((uint8_t)(0X01 << GpioCfg->GpioPin));
                }break;

                case GpioMode_EXS :
                {
                    *PxREN &= ~((uint8_t)(0X01 << GpioCfg->GpioPin));     // 禁止上下拉
                    *PxSEL |= ((uint8_t)(0X01 << GpioCfg->GpioPin));      // 设置为主外设模块功能
                    *PxSEL2 |= ((uint8_t)(0X01 << GpioCfg->GpioPin));     // PxSEL = 0b11
                    *PxDIR |= ((uint8_t)(0X01 << GpioCfg->GpioPin));
                }break;

                default: break;
    }
}


#endif



void Gpio_SetBit(uint8_t GpioPort, uint8_t GpioPin)
{
    if(GpioPort == GpioPort1)
    {
        P1OUT |= ((uint8_t)(0X01 << GpioPin));
    }
    else if(GpioPort == GpioPort2)
    {
        P2OUT |= ((uint8_t)(0X01 << GpioPin));
    }
    else if(GpioPort == GpioPort3)
    {
        P3OUT |= ((uint8_t)(0X01 << GpioPin));
    }
    else
    {
        return;
    }
}


void Gpio_ResetBit(uint8_t GpioPort, uint8_t GpioPin)
{
    if(GpioPort == GpioPort1)
    {
        P1OUT &= ~((uint8_t)(0X01 << GpioPin));
    }
    else if(GpioPort == GpioPort2)
    {
        P2OUT &= ~((uint8_t)(0X01 << GpioPin));
    }
    else if(GpioPort == GpioPort3)
    {
        P3OUT &= ~((uint8_t)(0X01 << GpioPin));
    }
    else
    {
        return;
    }
}


void Gpio_TogglePin(uint8_t GpioPort, uint8_t GpioPin)
{
    if(GpioPort == GpioPort1)
    {
        P1OUT ^= ~((uint8_t)(0X01 << GpioPin));
    }
    else if(GpioPort == GpioPort2)
    {
        P2OUT ^= ~((uint8_t)(0X01 << GpioPin));
    }
    else if(GpioPort == GpioPort3)
    {
        P3OUT ^= ~((uint8_t)(0X01 << GpioPin));
    }
    else
    {
        return;
    }
}




void Gpio_WritePin(uint8_t GpioPort, uint8_t GpioPin, BitAction BitVal)
{
    if(GpioPort == GpioPort1)
    {
        P1OUT &= ~((uint8_t)(0x01 << GpioPin));
        P1OUT |= ((uint8_t)(BitVal << GpioPin));
    }
    else if(GpioPort == GpioPort2)
    {
        P2OUT &= ~((uint8_t)(0x01 << GpioPin));
        P2OUT |= ((uint8_t)(BitVal << GpioPin));
    }
    else if(GpioPort == GpioPort3)
    {
        P3OUT &= ~((uint8_t)(0x01 << GpioPin));
        P3OUT |= ((uint8_t)(BitVal << GpioPin));
    }
    else
    {
        return;
    }
}
